import { version } from 'react';
import reactPlugin from 'eslint-plugin-react';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import vitestPlugin from '@vitest/eslint-plugin';
import prettierPlugin from 'eslint-plugin-prettier';

const baseConfig = {
  languageOptions: {
    parser: tsParser,
    sourceType: 'module',
  },
  plugins: {
    '@typescript-eslint': tsPlugin,
  },
};

const ignoreConfig = {
  ignores: [
    '**/dist',
    '**/lib',
    '**/node_modules',
    '**/packages/pdfkit/**',
    '**/packages/png-js/**',
    '**/packages/yoga/**',
    '**/packages/examples/**',
  ],
};

const globalsConfig = {
  languageOptions: {
    globals: {
      atob: false,
      Blob: false,
      BROWSER: false,
      Buffer: false,
      console: false,
      fetch: false,
      global: false,
      module: false,
      process: false,
      TextDecoder: false,
      TextEncoder: false,
      URL: false,
      window: false,
    },
  },
};

const jsConfig = {
  rules: {
    'array-callback-return': ['error', { allowImplicit: true }],
    'block-scoped-var': 'error',
    complexity: ['off', 20],
    'constructor-super': 'error',
    'default-case': ['error', { commentPattern: '^no default$' }],
    'default-case-last': 'error',
    'dot-notation': ['error', { allowKeywords: true }],
    eqeqeq: ['error', 'always', { null: 'ignore' }],
    'for-direction': 'error',
    'grouped-accessor-pairs': 'error',
    'guard-for-in': 'error',
    'getter-return': 'error',
    'max-classes-per-file': ['error', 1],
    'no-alert': 'error',
    'no-caller': 'error',
    'no-async-promise-executor': 'error',
    'no-case-declarations': 'error',
    'no-class-assign': 'error',
    'no-compare-neg-zero': 'error',
    'no-constructor-return': 'error',
    'no-await-in-loop': 'error',
    'no-console': 'warn',
    'no-cond-assign': 'error',
    'no-const-assign': 'error',
    'no-constant-condition': 'warn',
    'no-else-return': ['error', { allowElseIf: false }],
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-dupe-args': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-else-if': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-empty': 'error',
    'no-eval': 'error',
    'no-empty-character-class': 'error',
    'no-empty-pattern': 'error',
    'no-empty-static-block': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-ex-assign': 'error',
    'no-extra-boolean-cast': 'error',
    'no-fallthrough': 'error',
    'no-func-assign': 'error',
    'no-global-assign': 'error',
    'no-import-assign': 'error',
    'no-invalid-regexp': 'error',
    'no-implied-eval': 'error',
    'no-iterator': 'error',
    'no-irregular-whitespace': 'error',
    'no-loss-of-precision': 'error',
    'no-lone-blocks': 'error',
    'no-loop-func': 'error',
    'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
    'no-misleading-character-class': 'error',
    'no-new-native-nonconstructor': 'error',
    'no-nonoctal-decimal-escape': 'error',
    'no-obj-calls': 'error',
    'no-new-func': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-proto': 'error',
    'no-prototype-builtins': 'error',
    'no-script-url': 'error',
    'no-return-await': 'error',
    'no-redeclare': 'error',
    'no-return-assign': ['error', 'always'],
    'no-regex-spaces': 'error',
    'no-new-wrappers': 'error',
    'no-self-assign': 'error',
    'no-setter-return': 'error',
    'no-extra-label': 'error',
    'no-sequences': 'error',
    'no-throw-literal': 'error',
    'no-template-curly-in-string': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-this-before-super': 'error',
    'no-undef': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unsafe-optional-chaining': 'error',
    'no-unused-labels': 'error',
    'no-negated-in-lhs': 'off',
    'no-unused-vars': ['error', { ignoreRestSiblings: true }],
    'no-useless-backreference': 'error',
    'no-useless-concat': 'error',
    'no-useless-catch': 'error',
    'no-useless-escape': 'error',
    'no-useless-return': 'error',
    'no-void': 'error',
    'no-with': 'error',
    'prefer-promise-reject-errors': ['error', { allowEmptyReject: true }],
    'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
    'prefer-const': 'error',
    'prefer-rest-params': 'error',
    'prefer-spread': 'error',
    radix: 'error',
    'require-yield': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
    yoda: 'error',
  },
};

const reactConfig = {
  settings: {
    react: { version },
  },
  plugins: {
    react: reactPlugin,
  },
  rules: {
    'react/display-name': 'error',
    'react/jsx-key': 'error',
    'react/jsx-no-comment-textnodes': 'error',
    'react/jsx-no-duplicate-props': 'error',
    'react/jsx-no-target-blank': 'error',
    'react/jsx-no-undef': 'error',
    'react/jsx-uses-vars': 'error',
    'react/no-children-prop': 'error',
    'react/no-danger-with-children': 'error',
    'react/no-deprecated': 'error',
    'react/no-direct-mutation-state': 'error',
    'react/no-find-dom-node': 'error',
    'react/no-is-mounted': 'error',
    'react/no-render-return-value': 'error',
    'react/no-string-refs': 'error',
    'react/no-unescaped-entities': 'error',
    'react/no-unknown-property': 'error',
    'react/require-render-return': 'error',
  },
  languageOptions: {
    parserOptions: {
      jsxPragma: null,
      ecmaFeatures: {
        jsx: true,
      },
    },
  },
};

const vitestConfig = {
  files: ['**/*.test.js', '**/*.test.ts'],
  plugins: {
    vitest: vitestPlugin,
  },
  rules: {
    'vitest/expect-expect': 'error',
    'vitest/no-identical-title': 'error',
    'vitest/no-commented-out-tests': 'error',
    'vitest/valid-title': 'error',
    'vitest/valid-expect': 'error',
    'vitest/valid-describe-callback': 'error',
    'vitest/require-local-test-context-for-concurrent-snapshots': 'error',
    'vitest/no-import-node-test': 'error',
    'vitest/max-nested-describe': ['error', { max: 3 }],
  },
};

const tsConfig = {
  files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
  rules: {
    'constructor-super': 'off',
    'getter-return': 'off',
    'no-class-assign': 'off',
    'no-const-assign': 'off',
    'no-dupe-args': 'off',
    'no-dupe-class-members': 'off',
    'no-dupe-keys': 'off',
    'no-func-assign': 'off',
    'no-import-assign': 'off',
    'no-new-native-nonconstructor': 'off',
    'no-promise-executor-return': 'error',
    'no-obj-calls': 'off',
    'no-redeclare': 'off',
    'no-setter-return': 'off',
    'no-this-before-super': 'off',
    'no-undef': 'off',
    'no-unreachable': 'off',
    'no-unsafe-negation': 'off',
    'no-unused-vars': 'off',
    '@typescript-eslint/ban-ts-comment': 'error',
    '@typescript-eslint/no-array-constructor': 'error',
    '@typescript-eslint/no-duplicate-enum-values': 'error',
    '@typescript-eslint/no-empty-object-type': 'error',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-extra-non-null-assertion': 'error',
    '@typescript-eslint/no-misused-new': 'error',
    '@typescript-eslint/no-namespace': 'error',
    '@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
    '@typescript-eslint/no-require-imports': 'error',
    '@typescript-eslint/no-this-alias': 'error',
    '@typescript-eslint/no-unnecessary-type-constraint': 'error',
    '@typescript-eslint/no-unsafe-declaration-merging': 'error',
    '@typescript-eslint/no-unsafe-function-type': 'error',
    '@typescript-eslint/no-unused-expressions': 'error',
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/no-wrapper-object-types': 'error',
    '@typescript-eslint/prefer-as-const': 'error',
    '@typescript-eslint/prefer-namespace-keyword': 'error',
    '@typescript-eslint/triple-slash-reference': 'error',
  },
};

const prettierConfig = {
  plugins: {
    prettier: prettierPlugin,
  },
  rules: {
    'prettier/prettier': 'error',
  },
};

const config = [
  baseConfig,
  ignoreConfig,
  globalsConfig,
  jsConfig,
  reactConfig,
  vitestConfig,
  tsConfig,
  prettierConfig,
];

export default config;
